package com.ruoyi.web.controller.api;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.system.domain.SysEvaluate;
import com.ruoyi.system.domain.SysWord;
import com.ruoyi.system.mapper.SysEvaluateMapper;
import com.ruoyi.system.mapper.SysWordMapper;

@RestController
@RequestMapping("/api/pronunciation")
public class ApiPronunciationController {

    private static final Logger logger = LoggerFactory.getLogger(ApiPronunciationController.class);
    private static final String YOUDAO_URL = "https://openapi.youdao.com/iseapi";
    private static final String APP_KEY = "37b175319f5ec199";
    private static final String APP_SECRET = "6VTtCPS9oaRBNnWUBuarkzteakvDA0SQ";

    @Autowired
    private SysEvaluateMapper sysEvaluateMapper;
    @Autowired
    private SysWordMapper sysWordMapper;

    @PostMapping("/evaluate")
    public AjaxResult evaluatePronunciation(
    		@RequestParam("audio") MultipartFile audioFile,
    		@RequestParam("text") String text,
    		@RequestParam("unitId") Long unitId) {
        if (audioFile.isEmpty()) {
            return AjaxResult.error("请上传音频文件");
        }

        // 检查音频格式
        String originalFilename = audioFile.getOriginalFilename();
        if (originalFilename == null) {
            return AjaxResult.error("无效的文件名");
        }

        try {
            // 保存文件到指定的临时目录下
            String tempAudio = FileUploadUtils.upload(RuoYiConfig.getTempPath(), audioFile, MimeTypeUtils.MEDIA_EXTENSION);
            tempAudio = RuoYiConfig.getTempPath() + tempAudio.replace(Constants.RESOURCE_PREFIX + "/temp", "");

            // 转换后的WAV文件路径
            String outputFileName = UUID.randomUUID().toString() + ".wav";
            File outputFile = new File(RuoYiConfig.getTempPath(), outputFileName);
            
            // 使用FFmpeg进行音频转换
            ProcessBuilder processBuilder = new ProcessBuilder(
                "ffmpeg", "-i",
                tempAudio,
                "-acodec",
                "pcm_s16le",  // 16bit PCM编码
                "-ar",
                "16000",          // 16kHz采样率
                "-ac",
                "1",              // 单声道
                outputFile.getAbsolutePath()
            );

            Process process = processBuilder.start();
            // 记录FFmpeg的错误输出
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            StringBuilder errorOutput = new StringBuilder();
            String line;
            while ((line = errorReader.readLine()) != null) {
                errorOutput.append(line).append("\n");
            }

            int exitCode = process.waitFor();
            if (exitCode != 0) {
                logger.error("FFmpeg转换失败: {}\n{}", exitCode, errorOutput.toString());
                return AjaxResult.error("音频转换失败");
            }

            logger.info("音频转换成功: {}", outputFile.getAbsolutePath());

            // 准备API请求参数
            Map<String, String> params = new HashMap<>();
            params.put("appKey", APP_KEY);
            String q = IseV2Demo.loadAsBase64(outputFile.getAbsolutePath());
            logger.info("音频文件大小: {} bytes", outputFile.length());
            params.put("q", q);
            params.put("format", "wav");
            params.put("rate", "16000");
            params.put("channel", "1");
            params.put("docType", "json");
            params.put("type", "1");
            String salt = UUID.randomUUID().toString();
            params.put("salt", salt);
            params.put("langType", "en");
            params.put("text", text);
            String curtime = String.valueOf(System.currentTimeMillis() / 1000);
            params.put("curtime", curtime);
            String signStr = APP_KEY + IseV2Demo.truncate(q) + salt + curtime + APP_SECRET;
            String sign = IseV2Demo.getDigest(signStr);
            params.put("sign", sign);
            params.put("signType", "v2");

            logger.info("调用有道API，参数: text={}, salt={}, curtime={}", text, salt, curtime);
            // 调用评测API
            String resultStr = IseV2Demo.doRequest(YOUDAO_URL, params);
            logger.info("API响应结果: {}", resultStr);

            // 将JSON字符串转换为对象
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> resultMap = mapper.readValue(resultStr, Map.class);

            // 记录完整的API响应结构
            logger.info("API响应结构: {}", mapper.writeValueAsString(resultMap));

            // 检查API返回结果
            if (resultMap == null) {
                logger.error("API返回结果为空");
                return AjaxResult.error("评测失败：API返回结果为空");
            }

            // 检查错误信息
            if (resultMap.containsKey("error")) {
                Map<String, Object> error = (Map<String, Object>) resultMap.get("error");
                String errorMsg = error.containsKey("message") ? error.get("message").toString() : "未知错误";
                logger.error("API返回错误: {}", errorMsg);
                return AjaxResult.error("评测失败：" + errorMsg);
            }

            // 提取所需字段
            Map<String, Object> filteredResult = new HashMap<>();
            filteredResult.put("refText", text);
            
            // 直接从resultMap中获取评测数据
            if (resultMap.get("overall") == null) {
                logger.error("无法获取评分结果，resultMap: {}", resultMap);
                return AjaxResult.error("评测失败：无法获取评分结果");
            }
            
            // 提取关键评测指标
            filteredResult.put("overall", resultMap.get("overall"));

//            // 添加评测记录
//            SysWord sysWord = sysWordMapper.selectByWordName(text);
//            if (sysWord != null) {
//                SysEvaluate entity = new SysEvaluate();
//                entity.setStudentId(SecurityUtils.getLoginStudentId());
//                entity.setUnitId(unitId);
//                entity.setWordId(sysWord.getWordId());
//                entity.setScore(new BigDecimal(resultMap.get("overall").toString()));
//                sysEvaluateMapper.insert(entity);
//			}
            return AjaxResult.success("评测成功", filteredResult);
        } catch (Exception e) {
            logger.error("评测过程发生异常", e);
            String errorMessage = e.getMessage() != null ? e.getMessage() : "未知错误";
            return AjaxResult.error("评测失败：" + errorMessage);
        }
    }

    @PostMapping("/evaluate2")
    public AjaxResult evaluatePronunciation2(@RequestParam("audio") MultipartFile audioFile,
                                          @RequestParam("text") String text) {
        if (audioFile.isEmpty()) {
            return AjaxResult.error("请上传音频文件");
        }

        // 检查音频格式
        String originalFilename = audioFile.getOriginalFilename();
        if (originalFilename == null) {
            return AjaxResult.error("无效的文件名");
        }

        try {
            // 保存临时文件
            String tempDir = System.getProperty("java.io.tmpdir");
            String tempFileName = UUID.randomUUID().toString() + "_original" + getFileExtension(originalFilename);
            System.out.println("临时文件路径---" + tempDir + tempFileName);
            File tempFile = new File(tempDir, tempFileName);
            audioFile.transferTo(tempFile);
            logger.info("原始临时文件已保存: {}", tempFile.getAbsolutePath());

            // 转换后的WAV文件路径
            String outputFileName = UUID.randomUUID().toString() + ".wav";
            File outputFile = new File(tempDir, outputFileName);

            // 使用FFmpeg进行音频转换
            ProcessBuilder processBuilder = new ProcessBuilder(
                "ffmpeg", "-i",
                tempFile.getAbsolutePath(),
                "-acodec",
                "pcm_s16le",  // 16bit PCM编码
                "-ar",
                "16000",          // 16kHz采样率
                "-ac",
                "1",              // 单声道
                outputFile.getAbsolutePath()
            );

            Process process = processBuilder.start();
            // 记录FFmpeg的错误输出
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            StringBuilder errorOutput = new StringBuilder();
            String line;
            while ((line = errorReader.readLine()) != null) {
                errorOutput.append(line).append("\n");
            }

            int exitCode = process.waitFor();
            if (exitCode != 0) {
                logger.error("FFmpeg转换失败: {}\n{}", exitCode, errorOutput.toString());
                return AjaxResult.error("音频转换失败");
            }

            logger.info("音频转换成功: {}", outputFile.getAbsolutePath());

            // 准备API请求参数
            Map<String, String> params = new HashMap<>();
            params.put("appKey", APP_KEY);
            String q = IseV2Demo.loadAsBase64(outputFile.getAbsolutePath());
            logger.info("音频文件大小: {} bytes", outputFile.length());
            params.put("q", q);
            params.put("format", "wav");
            params.put("rate", "16000");
            params.put("channel", "1");
            params.put("docType", "json");
            params.put("type", "1");
            String salt = UUID.randomUUID().toString();
            params.put("salt", salt);
            params.put("langType", "en");
            params.put("text", text);
            String curtime = String.valueOf(System.currentTimeMillis() / 1000);
            params.put("curtime", curtime);
            String signStr = APP_KEY + IseV2Demo.truncate(q) + salt + curtime + APP_SECRET;
            String sign = IseV2Demo.getDigest(signStr);
            params.put("sign", sign);
            params.put("signType", "v2");

            logger.info("调用有道API，参数: text={}, salt={}, curtime={}", text, salt, curtime);
            // 调用评测API
            String resultStr = IseV2Demo.doRequest(YOUDAO_URL, params);
            logger.info("API响应结果: {}", resultStr);

            // 删除临时文件
            tempFile.delete();
            outputFile.delete();

            // 将JSON字符串转换为对象
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> resultMap = mapper.readValue(resultStr, Map.class);

            // 记录完整的API响应结构
            logger.info("API响应结构: {}", mapper.writeValueAsString(resultMap));

            // 检查API返回结果
            if (resultMap == null) {
                logger.error("API返回结果为空");
                return AjaxResult.error("评测失败：API返回结果为空");
            }

            // 检查错误信息
            if (resultMap.containsKey("error")) {
                Map<String, Object> error = (Map<String, Object>) resultMap.get("error");
                String errorMsg = error.containsKey("message") ? error.get("message").toString() : "未知错误";
                logger.error("API返回错误: {}", errorMsg);
                return AjaxResult.error("评测失败：" + errorMsg);
            }

            // 提取所需字段
            Map<String, Object> filteredResult = new HashMap<>();
            filteredResult.put("refText", text);
            
            // 直接从resultMap中获取评测数据
            if (resultMap.get("overall") == null) {
                logger.error("无法获取评分结果，resultMap: {}", resultMap);
                return AjaxResult.error("评测失败：无法获取评分结果");
            }
            
            // 提取关键评测指标
            filteredResult.put("overall", resultMap.get("overall"));

            return AjaxResult.success("评测成功", filteredResult);
        } catch (Exception e) {
            logger.error("评测过程发生异常", e);
            String errorMessage = e.getMessage() != null ? e.getMessage() : "未知错误";
            return AjaxResult.error("评测失败：" + errorMessage);
        }
    }

    private String getFileExtension(String filename) {
        int lastDotIndex = filename.lastIndexOf('.');
        return lastDotIndex > 0 ? filename.substring(lastDotIndex) : "";
    }
}